#import "HHUserCenter.h"
#import "HHUserConfig.h"
#import "HHUserPrivate.h"

#import <BCFoundation/BCFoundation.h>

@interface HHUserCenter ()<UIApplicationDelegate>

@property (nonatomic, strong) HHUserIdentites *identites;
@property (nonatomic, strong) HHUserModel *user;
@property (nonatomic, strong) NSHashTable *bindedDelegates;
/// 用户配置协议
@property (nonatomic, strong) HHUserConfig *config;

@end

@implementation HHUserCenter

///MARK: - system
static HHUserCenter *kUserCenterInstance = nil;
+ (instancetype)shared {
    static dispatch_once_t kUserCenterOnceToken;
    dispatch_once(&kUserCenterOnceToken, ^{
        kUserCenterInstance = [[HHUserCenter alloc] init];
    });
    return kUserCenterInstance;
}

- (instancetype)init {
    if (self = [super init]) {
        _bindedDelegates = [[NSHashTable alloc] initWithOptions:NSPointerFunctionsWeakMemory capacity:0];
        _userService = [[HHUserService alloc] init];
        _config = [[HHUserConfig alloc] init];
    }
    return self;
}

///MARK: - user
+ (HHUserIdentites *)identites {
    return kUserCenterInstance.identites;
}

+ (HHUserModel *)user {
    return kUserCenterInstance.user;
}

///MARK: - 配置
- (void)init_setup {
    [self.config hh_userSetup];
    // 加载缓存信息
    NSData *userIdentisData = [[NSUserDefaults standardUserDefaults] objectForKey:self.config.userIdenitiesKey];
    if (userIdentisData) {
        _identites = [NSKeyedUnarchiver unarchiveObjectWithData:userIdentisData];
    }

    NSData *userData = [[NSUserDefaults standardUserDefaults] objectForKey:self.config.userDataKey];
    if (userData) {
        _user = [NSKeyedUnarchiver unarchiveObjectWithData:userData];
    }
}

- (void)bind:(id<HHUserDelegate>)delegate {
    if (!delegate) {
        return;
    }
    if (![_bindedDelegates containsObject:delegate]) {
        [_bindedDelegates addObject:delegate];
    }
}

- (void)unbind:(id<HHUserDelegate>)delegate {
    [_bindedDelegates removeObject:delegate];
}

///MARK: - public
- (void)doReloadUserData:(void (^_Nullable)(BOOL success) )completion {
    @BCWeakify(self);
    [self.userService getUserCenterInfoWithCompletion:^(HHUserModel *_Nullable userModel) {
        @BCStrongify(self);
        if (userModel) {
            [self updateUserCenterData:userModel];
        }
        if (completion) {
            completion(userModel ? YES : NO);
        }
    }];
}

- (void)doLogout {
}

+ (NSString *)userLastLoginPhone {
    NSString *phone = [[NSUserDefaults standardUserDefaults] objectForKey:kHHUser_lastLoginPhone];
    if (!phone) {
        phone = @"";
    }
    return phone;
}

///MARK: - setter
- (void)setUserConfig:(NSObject<HHUserConfigProtocol> *)userConfig {
    _userConfig = userConfig;
    _config.configDelegate = userConfig;

    if ([self.userService isKindOfClass:HHUserService.class]) {
        HHUserService *service = (HHUserService *)self.userService;
        [service changeUserConfig:userConfig];
    }
}

///MARK: - private
/// 更新
- (void)updateUserIdentites:(HHUserIdentites *)identitesModel {
    if (identitesModel.token.length <= 0 && self.identites.token.length > 0) {
        identitesModel.token = self.identites.token;
    }
    self.identites = identitesModel;

    [self synchronizeIdentites];
}

- (BOOL)synchronizeIdentites {
    BOOL result = NO;
    if (self.identites.token > 0) {
        NSData *cacheData = [NSKeyedArchiver archivedDataWithRootObject:self.identites];
        [kBCUSERDEFAULT setObject:cacheData forKey:self.config.userIdenitiesKey];
        //保存手机号
        if (self.identites.phoneNum.length > 0) {
            [kBCUSERDEFAULT setObject:self.identites.phoneNum forKey:kHHUser_lastLoginPhone];
        }

        result = [kBCUSERDEFAULT synchronize];
    }
    return result;
}

- (void)updateUserCenterData:(HHUserModel *)userModel {
    self.user = userModel;

    [self synchronizeUser];
}

- (BOOL)synchronizeUser {
    BOOL result = NO;
    if (self.user) {
        NSData *cacheData = [NSKeyedArchiver archivedDataWithRootObject:self.user];
        [kBCUSERDEFAULT setObject:cacheData forKey:self.config.userDataKey];

        result = [kBCUSERDEFAULT synchronize];
    }
    return result;
}

///MARK: - event
///  手动通知登录成功
- (void)onManualLoginSuccess {
    //手动上传一次deviceToken
    NSString *userId = self.identites.doctorId;
    NSHashTable *bindDelegates = [self.bindedDelegates mutableCopy];
    for (id<HHUserDelegate> bindItem in bindDelegates) {
        if ([bindItem respondsToSelector:@selector(userCenter:didLoginSuccess:)]) {
            [bindItem userCenter:self didLoginSuccess:userId];
        }
    }
}

///  手动通知登录失败
- (void)onManualLoginFailed {
    NSHashTable *bindDelegates = [self.bindedDelegates mutableCopy];
    NSError *error = [NSError errorWithDomain:@"HHUserCenter" code:0 userInfo:@{ NSLocalizedDescriptionKey: @"登录失败，请重试" }];
    for (id<HHUserDelegate> bindItem in bindDelegates) {
        if ([bindItem respondsToSelector:@selector(userCenter:loginFailed:)]) {
            [bindItem userCenter:self loginFailed:error];
        }
    }
}

///  手动通知用户信息更新
- (void)onUserInfoUpdate {
    NSString *userId = self.identites.doctorId;
    NSHashTable *bindDelegates = [self.bindedDelegates mutableCopy];
    for (id<HHUserDelegate> bindItem in bindDelegates) {
        if ([bindItem respondsToSelector:@selector(userCenter:infoUpdate:)]) {
            [bindItem userCenter:self infoUpdate:userId];
        }
    }
}

///MARK: - service
- (void)doLogin:(NSString *)phoneNum password:(NSString *)pwd completion:(void (^_Nullable)(BOOL success) )completion {
    @BCWeakify(self);
    [self.userService userLogin:phoneNum password:pwd completion:^(BOOL success, HHUserIdentites *_Nullable identites) {
        @BCStrongify(self);
        if (success) {
            [self loginResultAction:identites];
        } else {
            [self onManualLoginFailed];
        }
    }];
}

- (void)sendSms:(NSString *)phoneNum actionType:(NSInteger)type completion:(void (^_Nullable)(BOOL success) )completion {
    [self.userService sendSms:phoneNum actionType:type completion:completion];
}

- (void)userLogin:(NSString *)phoneNum verifyCode:(NSString *)code completion:(void (^_Nullable)(BOOL success) )completion {
    @BCWeakify(self);
    [self.userService userLogin:phoneNum verifyCode:code completion:^(BOOL success, HHUserIdentites *_Nullable identites) {
        @BCStrongify(self);
        if (success) {
            [self loginResultAction:identites];
        } else {
            [self onManualLoginFailed];
        }
    }];
}

///MARK: - service action
- (void)loginResultAction:(HHUserIdentites *)identites {
    [self updateUserIdentites:identites];
    if ([self.config synchroniseUserData]) {
        [self doReloadUserData:NULL];
    }
    [self onManualLoginSuccess];
}

@end
